package com.pattern.beforeclass.proxy;

import org.springframework.aop.framework.DefaultAopProxyFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @Description
 * @Author Ping
 * @see java.lang.reflect.Proxy
 * @Date 2022/4/3 15:39
 **/
public class ProxyCore {

    public static void main(String args[]) {
        DefaultAopProxyFactory proxyFactory ;
        Target targetProxy = (Target) new ProxyFactory(new Target() {
            @Override
            public void work() {
                System.out.println("target was working.") ;
            }
        }, null, null).getProxy() ;

        targetProxy.work();


    }

}

interface A {
    default int method1(int a, int b) {
        System.out.println("method1 was called.") ;
        return a + b ;
    }
}
interface B {
    void method2() ;
}
interface BeforeAdvice {
    public void before() ;
}
interface AfterAdvice {
    public void after() ;
}
interface Target {
    public void work() ;
}
class ProxyFactory {
    Object targetObj ;
    BeforeAdvice beforeAdvice ;
    AfterAdvice afterAdvice ;

    public ProxyFactory(Object targetObj, BeforeAdvice beforeAdvice, AfterAdvice afterAdvice) {
        this.targetObj = targetObj;
        this.beforeAdvice = beforeAdvice;
        this.afterAdvice = afterAdvice;
    }
    public Object getProxy() {
        ClassLoader loader = ProxyFactory.class.getClassLoader() ;
        Class[] interfaces = targetObj.getClass().getInterfaces() ;
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                new BeforeAdvice() {
                    @Override
                    public void before() {
                        System.out.println("Before called.") ;
                    }
                }.before();
                method.invoke(targetObj, args) ;
                new AfterAdvice() {
                    @Override
                    public void after() {
                        System.out.println("after called.") ;
                    }
                }.after();

                return null;
            }
        } ;
        return Proxy.newProxyInstance(loader,interfaces, handler) ;

    }
}
